using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace LegoBotPrimaAbstractions
{
    public static class Ensure
    {
        [DebuggerStepThrough]
        public static void IsNotNegative<T>(T parameter, string parameterName) where T : struct, IComparable
        {
            if (parameter.CompareTo(default(T)) < 0)
            {
                throw new ArgumentOutOfRangeException(parameterName, String.Format("Parameter '{0}' cannot have negative value, it is = '{1}'", parameterName, parameter));
            }
        }

        [DebuggerStepThrough]
        public static void IsNotNull(object parameter, string parameterName)
        {
            if (parameter == null)
            {
                throw new ArgumentOutOfRangeException(parameterName, String.Format("Parameter '{0}' cannot be null", parameterName));
            }
        }

        [DebuggerStepThrough]
        public static void IsNotNullOrEmpty<T>(IEnumerable<T> parameter, string parameterName)
        {
            IsNotNull(parameter, parameterName);
            if (!parameter.GetEnumerator().MoveNext())
            {
                throw new ArgumentOutOfRangeException(parameterName, String.Format("Parameter '{0}' cannot be empty enumeration", parameterName));
            }
        }

        [DebuggerStepThrough]
        public static void IsNotNullOrEmpty<T>(ICollection<T> parameter, string parameterName)
        {
            IsNotNull(parameter, parameterName);
            if (parameter.Count == 0)
            {
                throw new ArgumentOutOfRangeException(parameterName, String.Format("Parameter '{0}' cannot be empty collection", parameterName));
            }
        }

        [DebuggerStepThrough]
        public static void IsNotNullOrEmpty(string parameter, string parameterName)
        {
            if (string.IsNullOrEmpty(parameter))
            {
                throw new ArgumentOutOfRangeException(parameterName, String.Format("Parameter '{0}' cannot be null or empty string", parameterName));
            }
        }

        [DebuggerStepThrough]
        public static void IsNotZeroOrNegative<T>(T parameter, string parameterName) where T : struct, IComparable
        {
            if (parameter.CompareTo(default(T)) <= 0)
            {
                throw new ArgumentOutOfRangeException(parameterName, String.Format("Parameter '{0}' cannot be zero or negative, it is = '{1}'", parameterName, parameter));
            }
        }

        [DebuggerStepThrough]
        public static void IsWithin<T>(T parameter, T from, T to, string parameterName) where T : struct, IComparable
        {
            if (parameter.CompareTo(from) < 0 || parameter.CompareTo(to) > 0)
            {
                throw new ArgumentOutOfRangeException(parameterName, String.Format("Parameter '{0}' must be withing ({1}-{2}) range, it is = '{3}'", parameterName, from, to, parameter));
            } 
        }
        
    }
}